<template>
  <div class="threshold-setting2">
    <PanelLabelOverflowTooltip ref="panelLabelOverflowTooltip" />
    <el-form
      ref="form"
      v-panel-label-overflow-tooltip="getPanelLabelOverflowTooltip()"
      class="form"
      label-position="right"
      :model="threshold_"
    >
      <VsFormItem
        v-if="showSwitch"
        :form="threshold_"
        path="isThreshold"
        :confs="fItemConf"
      />
      <div>
        <VsFormItem
          v-if="!dataType"
          :form="threshold_"
          path="dataType"
          :confs="fItemConf"
        />
        <el-table
          class="mapping-table"
          :data="threshold_.settings"
          :row-style="{ height: '25px' }"
          :header-row-style="{ height: '25px' }"
          max-height="500"
          :header-cell-style="{ lineHeight: '15px' }"
        >
          <el-table-column type="index">
            <template #default="{ $index }">
              <span class="index">{{ $index + 1 }}</span>
            </template>
          </el-table-column>
          <!-- number -->
          <el-table-column
            v-if="dataType === 'number'"
            :label="`${$demoi18n('panel.label.valueInterval')} eg: a <= x < b`"
            :min-width="130"
          >
            <template #header>
              <div class="th_wrap">
                <el-tooltip
                  placement="top"
                  :content="`${$demoi18n('panel.label.valueInterval')} eg: a <= x < b`"
                  :effect="xvueTheme"
                >
                  <span>
                    {{ $demoi18n('panel.label.valueInterval') }}
                    <span style="font-weight: normal; font-size:12px;"> eg: a &lt;= x &lt; b</span>
                  </span>
                </el-tooltip>
                <el-dropdown :popper-class="`reavg-color-themes-pop ${visualThemeClassName}`">
                  <el-button type="primary" link>{{ $demoi18n('threshold-setting2.reAvgRange') }}</el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item>
                        <div @click="reAvgRange()">{{ $demoi18n('threshold-setting2.fullApiData') }}</div>
                      </el-dropdown-item>
                      <el-dropdown-item>
                        <div @click="reAvgRange(true)">{{ $demoi18n('threshold-setting2.pageLinkageData') }}</div>
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </template>
            <template #default="scope">
              <div
                v-if="scope.row.isDefault"
                class="default"
              >{{ $demoi18n('commonMap.other') }}</div>
              <div
                v-else
                class="range"
              >
                <el-input
                  v-if="scope.row.range[0] === thresholdMinNum"
                  size="default"
                  model-value="-∞"
                  disabled
                ></el-input>
                <el-input-number
                  v-else
                  v-model="scope.row.range[0]"
                  :placeholder="$demoi18n('panel.thresholdSetting.leftVal')"
                  size="default"
                  :controls="false"
                  @blur="checkThreshold()"
                ></el-input-number>

                <span class="splitor">-</span>

                <el-input
                  v-if="scope.row.range[1] === thresholdMaxNum"
                  size="default"
                  model-value="+∞"
                  disabled
                ></el-input>
                <el-input-number
                  v-else
                  v-model="scope.row.range[1]"
                  :placeholder="$demoi18n('panel.thresholdSetting.rightVal')"
                  size="default"
                  :controls="false"
                  @blur="checkThreshold()"
                ></el-input-number>
              </div>
            </template>
          </el-table-column>

          <!-- string -->
          <el-table-column
            v-if="dataType === 'string'"
            :label="$demoi18n('panel.thresholdSetting.parameterCharacter')"
            :render-header="renderTooltipHeader"
          >
            <template #default="scope">
              <div
                v-if="scope.row.isDefault"
                class="default"
              >{{ $demoi18n('panel.label.default') }}</div>
              <ValueInputer
                v-else
                v-model:value="scope.row.value"
                :enum-values="options"
              />
            </template>
          </el-table-column>

          <!-- fields -->
          <el-table-column
            v-for="(field, key) in fields"
            :key="key"
            :label="field.label"
            :min-width="getColWidth(field.type)"
          >
            <template #header>
              <div class="th_wrap">
                <ThCell :label="field.label" />
                <ThresholdColorTheme
                  v-if="field.type === 'color'"
                  :colorTheme="threshold_.colorTheme"
                  :colorThemes="topForm.colorThemes"
                  @select-color-theme="selectColorTheme"
                  @save-color-themes="saveColorThemes"
                />
              </div>
            </template>
            <template #default="scope">
              <IconEditor
                v-if="field.type === 'icon'"
                :icon="scope.row.valConf[key]"
                @save="saveIcon($event, scope.row, key)"
                @delete="deleteIcon($event, scope.row, key)"
              />
              <ColorPicker
                v-else-if="field.type === 'color'"
                v-model:value="scope.row.valConf[key]"
                :colors="[]"
              />
              <ValueInputer
                v-else
                v-model:value="scope.row.valConf[key]"
                :value-type="upper(field.type)"
                :required="!!field.required"
              />
            </template>
          </el-table-column>

          <!-- action -->
          <el-table-column :min-width="50">
            <template #default="scope">
              <el-button
                :disabled="scope.row.isDefault"
                icon="Delete"
                :link="true"
                type="primary"
                @click.stop="deleteCurRow(scope.row)"
              ></el-button>
            </template>
            <template #header>
              <el-button
                :title="$demoi18n('btn.add')"
                icon="Plus"
                :link="true"
                type="primary"
                @click.stop="addNewRow()"
              ></el-button>
              <el-button
                :title="$demoi18n('threshold-setting2.resetTip')"
                icon="Refresh"
                :link="true"
                type="primary"
                @click.stop="confirmReCutRange()"
              ></el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-form>
  </div>
</template>
<script lang='jsx'>
import Variables from '@/common/variables.js';
import ColorPicker from '@/components/common/color-picker/color-picker.vue';
import IconEditor from '@/components/common/icon/icon-editor.vue';
import PanelLabelOverflowTooltip from '@/components/common/overflow-tooltip/overflow-tooltip.vue';
import ValueInputer from '@/components/common/value-inputer/value-inputer.vue';
import VsFormItem from '@/components/common/vs-form-item/vs-form-item.vue';
import { $demoi18n } from '@/utils/lang.js';
import { firstToUpper, isNum, validChildForms, $warnConfirm } from '@/utils/util.js';
import { mapState } from 'vuex';
import fItemConf from './form-item-config.js';
import ThresholdColorTheme from '@/components/common-map/config/threshold-color-theme.vue';
import ThCell from '@/components/common/th-cell/th-cell.vue';

// 参考平面地图颜色
const dfColors = {
  light: ['#37E637', '#F9D900', '#FC9B1E', '#FF5A5A', '#A7A8C7'],
  dark: ['#37E637', '#FFED75', '#EDA85D', '#F12424', '#A7A8C7'],
  real: ['#37E637', '#FFED75', '#EDA85D', '#F12424', '#A7A8C7'],
};

export default {
  components: {
    VsFormItem,
    ValueInputer,
    fItemConf,
    IconEditor,
    ColorPicker,
    PanelLabelOverflowTooltip,
    ThresholdColorTheme,
    ThCell,
  },
  provide() {
    return {
      addChild: formVm => {
        this.validateForms.push(formVm);
      },
    };
  },
  props: {
    topForm: { // 相当于组件的config.property
      type: Object,
      default: () => ({}),
    },
    threshold: Object,
    dataType: String, // string, number
    fields: {
      type: Object,
      default: () => ({
        color: { type: 'color', default: '#ff0000', label: $demoi18n('word.color') },
        icon: { type: 'icon', default: {}, label: $demoi18n('word.icon') },
        unit: { type: 'input', default: '', label: $demoi18n('word.unit') },
      }),
    },
    options: {
      type: Array,
      default: () => [],
    },
    cutNum: Number, // 几等分
    min: Number, // 几等分依据最小值
    max: Number, // 几等分依据最大值

    // 显示阈值开关选项
    showSwitch: {
      type: Boolean,
      default: false,
    },

    fieldKey: String, // 使用预览面api结果做范围最大最小值，需要用到的字段key
  },
  data() {
    return {
      threshold_: {},
      fItemConf,
      xvueTheme: window._adoPremise.uc.theme,
      thresholdMinNum: Variables.thresholdMinNum,
      thresholdMaxNum: Variables.thresholdMaxNum,
      validateForms: [],
    };
  },
  computed: {
    ...mapState({
      componentStyle: state => state.VisualComponentsModule.formComponentStyle,
    }),
  },
  watch: {
    threshold() {
      this.initThreshold();
    },
  },
  created() {
    this.initThreshold();
  },
  mounted() {
    if (!this.$refs.form) {
      return;
    }
    this.validateForms.push(this.$refs.form);
  },
  methods: {
    getPanelLabelOverflowTooltip() {
      return {
        parentComp: this,
      };
    },

    initThreshold(reset = false) {
      if (this.threshold && this.threshold.dataType && !reset) {
        this.threshold_ = JSON.parse(JSON.stringify(this.threshold));
      } else {
        this.threshold_ = {
          dataType: 'number',
          isThreshold: true,
          settings: [],
        };

        this.reCutRange();
      }
    },

    addDfSetting() {
      let dfItem = this.threshold_.settings.find(n => n.isDefault);
      if (!dfItem) {
        dfItem = {
          dataType: this.threshold_.dataType,
          isDefault: true,
          value: '',
          range: [],
          valConf: this.getDfValConf(),
        };
        this.threshold_.settings.push(dfItem);
      }
    },

    // 重新排序，保证默认设置在最后一条
    sortSettings() {
      const { settings } = this.threshold_;
      const dfItem = settings.find(n => n.isDefault);
      const otherItems = settings.filter(n => !n.isDefault);
      this.threshold_.settings = [...otherItems, dfItem];
    },

    confirmReCutRange() {
      $warnConfirm(this.$demoi18n('threshold-setting2.resetConfirm'), this.$demoi18n('popup.title.tips')).then(() => {
        this.reCutRange();
      });
    },

    // 4等分重置
    reCutRange() {
      const settings = [];
      const { min, max } = this;
      const cutNum = 4;
      if (this.dataType === 'number' && cutNum) {
        const step = (max - min) / cutNum;
        for (let i = 0; i < cutNum; i++) {
          const item = {};
          item.dataType = 'number';
          item.range = [Math.floor(i * step + min), Math.floor((i + 1) * step + min)];
          item.valConf = this.getDfValConf(i);
          settings.push(item);
        }
        const len = settings.length;
        settings[0].range[0] = Variables.thresholdMinNum;
        settings[len - 1].range[1] = Variables.thresholdMaxNum;
      }

      this.threshold_.settings = settings;
      this.addDfSetting();
    },

    // 重新分配数值
    reAvgRange(usePreviewResult = false) {
      let { min, max } = this;
      if (usePreviewResult) { // 使用预览面结果
        const { curPreviewVm } = window.visualComp;
        if (!curPreviewVm?.layer?.config?.property?.id) {
          this.$message({
            message: this.$demoi18n('threshold-setting2.noPreviewDataTip'),
            type: 'warning',
          });
          return;
        }
        const values = curPreviewVm.apiResult.map(n => n[this.fieldKey]);
        if (values.length > 0) {
          min = Math.min(...values);
          max = Math.max(...values);
        } else {
          min = 0;
          max = 0;
        }
      }

      if (this.dataType === 'number') {
        const settings = this.threshold_.settings.filter(n => !n.isDefault);
        const len = settings.length;
        const step = (max - min) / len;
        for (let i = 0; i < len; i++) {
          const item = settings[i];
          item.range = [Math.floor(i * step + min), Math.floor((i + 1) * step + min)];
        }
        settings[0].range[0] = Variables.thresholdMinNum;
        settings[len - 1].range[1] = Variables.thresholdMaxNum;
      }
    },

    checkThreshold() {
      let errorText = '';

      // -------- string
      if (this.dataType === 'string') {
        const textArray = this.threshold_.settings.map(n => n.value);
        const textSet = new Set(textArray);
        textSet.delete('');
        if (textSet.size < textArray.length) {
          errorText = this.$demoi18n('message.duplicateStringThreshold');
          this.$message.error(errorText);
          return false;
        }
      }

      // --------- number
      if (this.dataType === 'number') {
        const rangeArray = [];
        this.threshold_.settings.forEach((item, index) => {
          rangeArray[index] = item.range;
        });
        for (let i = 0; i < rangeArray.length; i++) {
          if (rangeArray[i][0] >= rangeArray[i][1]) {
            errorText = this.$demoi18n('message.wrongThresholdRange');
            this.$message.error(errorText);
            return false;
          }
        }
        for (let i = 0; i < rangeArray.length; i++) {
          for (let j = 0; j < i; j++) {
            if (
              (rangeArray[i][0] >= rangeArray[j][0] && rangeArray[i][0] < rangeArray[j][1]) ||
              (rangeArray[i][1] > rangeArray[j][0] && rangeArray[i][1] < rangeArray[j][1])
            ) {
              errorText = this.$demoi18n('message.thresholdRepetition');
              this.$message.error(errorText);
              return false;
            }
          }
        }
      }

      return true;
    },

    upper(key) {
      return firstToUpper(key);
    },

    saveIcon(iconConf, row, key) {
      row.valConf[key] = iconConf;
    },

    deleteIcon(iconConf, row, key) {
      row.valConf[key] = {};
    },

    addNewRow() {
      const { dataType, settings } = this.threshold_;
      const _settings = settings.filter(n => !n.isDefault);
      const len = _settings.length;
      const item = {};
      switch (dataType) {
        case 'number': {
          let start = 0;
          let end = 1;
          if (len > 0) {
            const endRange = _settings[len - 1].range;
            start = endRange[1];
            if (start === Variables.thresholdMaxNum) {
              endRange[1] = endRange[0] + 1;
              start = endRange[1];
              end = Variables.thresholdMaxNum;
            } else {
              end = start + 1;
            }
          }

          item.range = [start, end];
          break;
        }
        case 'string': {
          item.value = '';
          break;
        }
        default: break;
      }

      item.valConf = this.getDfValConf(len);
      settings.push(item);
      this.sortSettings();
    },

    getDfValConf(arrIndex = null) {
      const valConf = {};
      Object.entries(this.fields).map(([i]) => {
        const n = this.fields[i];
        let df = n.default;

        // 颜色无默认值
        if (n.type === 'color' && !n.default) {
          const colors = dfColors[this.componentStyle];
          const len = colors.length;
          if (!isNum(arrIndex) || arrIndex >= len) {
            df = colors[len - 1];
          } else {
            df = colors[arrIndex];
          }
        }

        valConf[i] = df;
      });
      return valConf;
    },

    deleteCurRow(item) {
      const { settings } = this.threshold_;
      const index = settings.indexOf(item);
      settings.splice(index, 1);
    },

    getColWidth(type) {
      const widths = {
        color: 40,
        icon: 40,
        string: 80,
      };
      return widths[type];
    },

    // 保存阈值，供外部调用
    async saveThreshold() {
      const errors = await validChildForms(this.validateForms);
      if (errors.length) {
        return false;
      }
      const threshold = JSON.parse(JSON.stringify(this.threshold_));
      return threshold;
    },

    selectColorTheme(colorTheme) {
      this.threshold_.colorTheme = JSON.parse(JSON.stringify(colorTheme));
      this.threshold_.settings.filter(n => !n.isDefault).forEach((n, i) => {
        const cutNum = this.threshold_.settings.length - 2 || 1; // 减去“其他”项1，还要减1，因为最后一条为颜色终点值
        const percent = (1 / cutNum) * i;
        n.valConf.color = this.getRangeColor(colorTheme[0], colorTheme[1], percent);
      });
    },

    saveColorThemes(colors) {
      this.topForm.colorThemes = JSON.parse(JSON.stringify(colors));
    },

    renderTooltipHeader({ column }) {
      return (
        <el-tooltip placement="top" content={column.label} effect={this.xvueTheme}>
          <span>{column.label}</span>
        </el-tooltip>
      );
    },

    // 将十六进制颜色转换为RGB格式
    hexToRGB(hex) {
      const r = parseInt(hex.slice(1, 3), 16);
      const g = parseInt(hex.slice(3, 5), 16);
      const b = parseInt(hex.slice(5, 7), 16);
      return [r, g, b];
    },

    // 将RGB颜色转换为十六进制格式
    RGBToHex(rgb) {
      const hex = rgb.map(c => {
        const _hex = c.toString(16);
        return _hex.length === 1 ? `0${_hex}` : _hex;
      });
      return `#${hex.join('')}`;
    },

    // 获取两个颜色之间的中间值
    getRangeColor(startColor, endColor, percent) {
      const startRGB = this.hexToRGB(startColor);
      const endRGB = this.hexToRGB(endColor);

      const r = startRGB[0] * (1 - percent) + endRGB[0] * percent;
      const g = startRGB[1] * (1 - percent) + endRGB[1] * percent;
      const b = startRGB[2] * (1 - percent) + endRGB[2] * percent;
      const midColor = this.RGBToHex([Math.round(r), Math.round(g), Math.round(b)]);
      return midColor;
    },

  },
};
</script>
<style lang="less" scoped>
.threshold-setting2 {
  :deep(.mapping-table) {
    th,
    td {
      padding: 5px 0;
    }
    .cell {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      .default {
        text-align: right;
      }
      .th_wrap{
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
      .index{
        display: block;
        text-align: center;
      }
    }
  }

  :deep(.range) {
    display: flex;
    > .el-input {
      width: 49%;
      font-size: 16px;
    }
    > .el-input-number {
      width: 49%;
    }
    .el-input__inner {
      padding-left: 2px;
      padding-right: 2px;
      text-align: center;
      font-family: initial;
    }
    .splitor {
      padding: 0 2px;
    }
  }
}
</style>
